package event

import (
	"fmt"
	"sync"

	"hawkeye/protocol"
)

// EventHandler 事件处理器接口
type EventHandler func(ctx *Context, data interface{}) error

// Context 事件上下文
type Context struct {
	ConnID     string
	RemoteAddr string
	Message    *protocol.Message
}

// Manager 事件管理器
type Manager struct {
	handlers map[protocol.EventType]EventHandler
	mutex    sync.RWMutex
}

// NewManager 创建新的事件管理器
func NewManager() *Manager {
	return &Manager{
		handlers: make(map[protocol.EventType]EventHandler),
	}
}

// RegisterHandler 注册事件处理器
func (m *Manager) RegisterHandler(eventType protocol.EventType, handler EventHandler) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	if _, exists := m.handlers[eventType]; exists {
		return fmt.Errorf("事件处理器已存在: %d", eventType)
	}

	m.handlers[eventType] = handler
	return nil
}

// UnregisterHandler 注销事件处理器
func (m *Manager) UnregisterHandler(eventType protocol.EventType) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	if _, exists := m.handlers[eventType]; !exists {
		return fmt.Errorf("事件处理器不存在: %d", eventType)
	}

	delete(m.handlers, eventType)
	return nil
}

// HandleEvent 处理事件
func (m *Manager) HandleEvent(ctx *Context, eventType protocol.EventType, data interface{}) error {
	m.mutex.RLock()
	handler, exists := m.handlers[eventType]
	m.mutex.RUnlock()

	if !exists {
		return fmt.Errorf("未注册的事件处理器: %d", eventType)
	}

	return handler(ctx, data)
}

// GetRegisteredEvents 获取已注册的事件类型
func (m *Manager) GetRegisteredEvents() []protocol.EventType {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	events := make([]protocol.EventType, 0, len(m.handlers))
	for eventType := range m.handlers {
		events = append(events, eventType)
	}

	return events
}

// HasHandler 检查事件处理器是否存在
func (m *Manager) HasHandler(eventType protocol.EventType) bool {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	_, exists := m.handlers[eventType]
	return exists
}

// NewContext 创建新的事件上下文
func NewContext(connID, remoteAddr string, msg *protocol.Message) *Context {
	return &Context{
		ConnID:     connID,
		RemoteAddr: remoteAddr,
		Message:    msg,
	}
}
